﻿using System;

namespace FrameOperateSync
{
    public class FrameSyncClient
    {
        private int _playerId;
        private OperateLogicManager operateManager;
        private RenderLogicManager renderManager;
        private FrameNetwork network;
        private FrameTicker logicTicker;
        private FrameTicker renderTicker;

        public FrameSyncClient(int playerId)
        {
            _playerId = playerId;
        }

        public void SetFrameParser(IFrameParser parser)
        {
            RenderData.SetParser(parser);
        }

        public void SetLoger(IFrameLoger loger)
        {
            Loger.SetLoger(loger);
        }

        public void BeginSync()
        {
            operateManager = new OperateLogicManager(_playerId);
            renderManager = new RenderLogicManager();
            logicTicker = new FrameTicker();
            renderTicker = new FrameTicker();
            network = new FrameNetwork(NetMode.localTest, operateManager, renderManager);
            logicTicker.EventTicker += operateManager.OnFrameTick;
            renderTicker.EventTicker += renderManager.OnFrameRender;
            FrameTicker.Run(logicTicker);
            FrameTicker.Run(renderTicker);
        }

        public void EndSync()
        {
            logicTicker.EventTicker -= operateManager.OnFrameTick;
            renderTicker.EventTicker -= renderManager.OnFrameRender;
            FrameTicker.Stop(logicTicker);
            FrameTicker.Stop(renderTicker);
        }

        public void PauseSync()
        {
            FrameTicker.Pause(logicTicker);
            FrameTicker.Pause(renderTicker);
        }

        public void ResumeSync()
        {
            FrameTicker.Resume(logicTicker);
            FrameTicker.Resume(renderTicker);
        }

        public void SyncOperate(int operateCode, IRenderData data)
        {
            if (operateManager == null)
                throw new Exception("OperateLogicManager is not invalid");
            operateManager.OperateExcute(operateCode, data);
        }

        public void SyncOperate(IRenderData data)
        {
            var id = FrameSyncCenter.GetOperateId(data);
            SyncOperate(id, data);
        }

        public static void GameRenderUpdate()
        {
            while (RenderData.renderRecvQueue.Count > 0)
            {
                var item = RenderData.renderRecvQueue.Dequeue();
                if (item.LogicCode == -1)
                    continue;
                var type = FrameSyncCenter.GetRenderType(item.LogicCode);
                FrameSyncCenter.OnRender(item.PlayerId, item.LogicCode, item.KeyFrameIndex, item.FrameIndex, RenderData.FromBytes(item.Data, type));
            }
        }
    }
}
